﻿using Newtonsoft.Json;
using System.Diagnostics;
using System.Dynamic;

namespace Wargame_V3_1
{
    /// <summary>
    /// 动态构建action示例，初始化后，可通过action.property（如action.ObjID）直接获得属性值，也可通过action.property = value修改属性值
    /// </summary>
    public class Action : DynamicObject
    {
        // 记录action各属性的类型，在ActionModels.json中定义
        private Dictionary<string, string> __actionModel = new Dictionary<string, string>();

        // 记录action各属性的值，类型由__actionModel中定义
        private Dictionary<string, object> __actionData = new Dictionary<string, object>();

        /// <summary>
        /// 构造方法：根据输入的字符串式字典actionDict，转换属性值类型后，初始化action
        /// </summary>
        /// <param name="allActionModels">从文件ActionModels.json中读取的action模型</param>
        /// <param name="actionDict">字符串式字典</param>
        public Action(Dictionary<string, Dictionary<string, string>> allActionModels, Dictionary<string, string> actionDict)
        {
            if (actionDict.ContainsKey("Type"))
            {
                string actionName = actionDict["Type"] + "Action";
                if (allActionModels.ContainsKey(actionName))// 动作模型是否包含传入的动作
                {
                    __actionModel = allActionModels[actionName];
                    foreach (KeyValuePair<string, string> item in actionDict)
                    {
                        if (__actionModel.ContainsKey(item.Key))
                        {
                            string dataType = __actionModel[item.Key];
                            dynamic value = ChangeType.ConvertString(item.Value, dataType);
                            __actionData.Add(item.Key, value);
                        }
                        else
                        {
                            __actionData.Add(item.Key, item.Value);
                            Trace.TraceWarning($"{item.Key}的属性不在action模型中。");
                        }
                    }
                }
                else
                {
                    Trace.TraceError($"ActionModels中没有{actionName}的action模型");
                    throw new Exception($"ActionModels中没有{actionName}的action模型");
                }
            }
            else
            {
                Trace.TraceError("输入的action有误，没有Type数据");
                throw new Exception("输入的action有误，没有Type数据");
            }
        }

        /// <summary>
        /// 构造方法：输入类型良好的字典actionDict，初始化action
        /// </summary>
        /// <param name="allActionModels">从文件ActionModels.json中读取的action模型</param>
        /// <param name="actionDict">类型良好的action字典</param>
        public Action(Dictionary<string, Dictionary<string, string>> allActionModels, Dictionary<string, object> actionDict)
        {
            if (actionDict.ContainsKey("Type"))
            {
                string actionName = actionDict["Type"] + "Action";
                if (allActionModels.ContainsKey(actionName))
                {
                    __actionModel = allActionModels[actionName];
                    __actionData = actionDict;
                }
                else
                {
                    Trace.TraceError($"ActionModels中没有{actionName}的action模型");
                    throw new Exception($"ActionModels中没有{actionName}的action模型");
                }
            }
            else
            {
                Trace.TraceError("输入的action有误，没有Type数据");
                throw new Exception("输入的action有误，没有Type数据");
            }
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            if (__actionData.ContainsKey(binder.Name))
            {
                result = __actionData[binder.Name];
                return true;
            }
            else
            {
                result = null;
                Trace.TraceWarning($"当前action中没有属性{binder.Name}");
                return false;
            }
        }

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            string property = binder.Name;
            if (Array.IndexOf(new string[] { "ObjID", "Type" }, property) != -1) // 输入的property是"ObjID"或"Type"，不可更改。
            {
                Trace.TraceWarning($"action的属性{property}不可更改");
                return true;
            }
            if (__actionModel.ContainsKey(property))
            {
                string typeString = __actionModel[property];
                if (value.GetType() != Type.GetType(ChangeType.ToFullName(typeString))) // 判断value的类型与属性类型是否相符
                {
                    Trace.TraceWarning($"输入{value}的类型与action的属性{property}类型不匹配，属性值修改不成功");
                    return true;
                }
                __actionData[property] = value;
                return true;
            }
            else
            {
                Trace.TraceWarning($"当前action中没有属性{property}");
                return false;
            }
        }

        public override string ToString()
        {
            return JsonConvert.SerializeObject(__actionData);
        }
    }
}
